package cn.nr19.jian


import cn.nr19.jian.exception.E2ParserException
import cn.nr19.jian.exception.ParserException
import cn.nr19.jian.factory.JsFactory
import cn.nr19.jian.`object`.JianLeiApi
import cn.nr19.jian.utils.JsoupParserUtils
import cn.nr19.jian.utils.OItem
import org.json.JSONArray
import org.json.JSONObject
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.parser.Parser
import org.jsoup.parser.XmlTreeBuilder
import org.jsoup.select.Elements
import java.nio.charset.Charset


/**
 * E2解析器操作类
 * by Jen. 2020.12.
 */

object E2Factory {
    fun text(content: String, reg: String,lei : JianLeiApi) : String{
        val ss = list(content, reg,lei) ?: return ""
        if (ss.size > 0){
            return ss[0]
        }
        return ""
    }
    fun list(content: String, reg: String,lei : JianLeiApi) : MutableList<String>?{
        return if (reg == ".all()" || reg == ".q()") {
            val ls = ArrayList<String>()
            ls.add(content)
            ls
        }
        else if(!reg.startsWith(".")){
            val ls = ArrayList<String>()
            if (reg.startsWith("js=")){
                lei.pJianSystemFun("evalJS",reg.substring(3))?.let {
                    ls.add(Jian.Str(it))
                }
            }
            else if (reg.isEmpty()){
                ls.add(content)
            }
            else{
                throw E2ParserException("E2语法有误 ${reg}")
            }
            ls
        }
        else {
            try {
                E2Parser(content, reg,lei).start().let {
                    it
                }
            }catch (e : Exception){
                e.printStackTrace()
                throw E2ParserException("E2解析出错 $e : $reg")
            }
        }

    }



    /**
     * @param content 源代码
     */
    class E2Parser(val content: String, val reg: String,val lei : JianLeiApi) {

        init {

        }

        // 解析已结束
        var endPraser = false

        // 已存入库的内容 比如使用 xu 则先保留上次操作的数据
        val oC = ArrayList<String>()

        // 当前进行操作的内容
        val pC = ArrayList<String>()

        // 上一个参数为 ix(1 拼接数组) 还是 tx (2 拼接文本) ，为1 则最终 oc.addall(pc) 为2则 oc 最后一个成员加上 pc 第一个成员
        var oL = 0

        fun start(): MutableList<String>? {
            if (reg.isEmpty()) return null

            endPraser = false
            oC.clear() // 存入不变的值
            pC.clear() // 进行中的值

            // 起始内容
            pC.add(content)

            // 当前解析的函数位置 从 1
            var curFunPos = 0 // 这里为零 处理前时 ++

            // 读解析规则
            val tokens = E2TokenPraser(reg)
            var tk = tokens.next()
            while (tk != null) {
                curFunPos++
                if (endPraser) break


                try {
                    // 分类命令 影响上下文的直接本函数内处理
                    when (tk.a) {

                        // or 否则 若前面取值为空则继续，否则关掉
                        "or" -> {
                            if (pC.size >= 1 && pC[0] != "") {
                                endPraser = true
                            }else{
                                endPraser = false
                                pC.clear()
                                pC.add(content)
                            }
                        }

                        // xu 记录
                        "xu", "ix"  -> {
                            oL = 1
                            oC.addAll(pC)
                            pC.clear()
                            pC.add(content)

                        }

                        // 插入一条数组
                        "ij"->{
                            pC.add(tk.v)
                        }

                        // 删除数组 正则
                        "is"->{
                            val xs = ArrayList<String>()
                            for (s in pC) {
                                if (!s.matches(Regex(tk.v))) xs.add(s)
                            }

                            pC.clear()
                            pC.addAll(xs)
                        }

                        // 判断 留住数组 正则
                        "il"->{
                            val xs = ArrayList<String>()
                            for (s in pC) {
                                if (s.matches(Regex(tk.v))) xs.add(s)
                            }
                            pC.clear()
                            pC.addAll(xs)
                        }

                        "tx","c" -> {
                            oL = 2
                            // 当前处理内容不为源文本时，则添加的不变值中
                            if (pC.size != 0 && pC[0].isNotEmpty() && pC[0] != content ) {
                                if (oC.size >= 1) {
                                    oC[oC.size - 1] += pC[0]
                                } else {
                                    oC.add(pC[0])
                                }
                            }

                            // 若含参数，则先插入
                            if (tk.v != ""){
                                if (oC.size >= 1) {
                                    oC[oC.size - 1] += tk.v
                                } else {
                                    oC.add(tk.v)
                                }
                            }

                            // 需将参数存入
                            pC.clear()
                            pC.add(content)
                        }

                        // 变量
                        "var","vx" -> {
                            // 当前处理内容不为源文本时，则添加到已处理值中
                            if (pC.size != 0 && pC[0].isNotEmpty() && pC[0] != content ) {
                                if (oC.size >= 1) {
                                    oC[oC.size - 1] += pC[0]
                                } else {
                                    oC.add(pC[0])
                                }
                            }

                            // 需将参数存入
                            pC.clear()
                            pC.add( Jian.Str(lei.getVar(tk.v)))
                        }

                        // 读取网络数据
                        "jz","jz2","get0","get1" -> {

                            // 若为第一个函数，则清除处理中内容
                            if (curFunPos == 1) pC.clear()

                            // 若参数含值则取值中地址，则需将前面所读取内容先存储
                            else if (tk.v != ""){
                                if (oC.size >= 1) {
                                    oC[oC.size - 1] += pC[0]
                                } else {
                                    oC.add(pC[0])
                                }

                            }

                            // 否则地址为前面所取到的内容
                            else{
                                tk.v = pC[0]
                            }

                            pC.clear()

                            if (tk.a == "jz2" || tk.a == "get0"){
                                lei.pJianSystemFun("读源码_JSOUP",tk.v).let { it->
                                    if (it is String)  pC.add(it)
                                    else {
                                        throw E2ParserException("无法取源码：${tk!!.v}" ,0)
                                    }
                                }
                            }
                            else{
                                lei.pJianSystemFun("读源码",tk.v).let { it->
                                    if (it is String)  pC.add(it)
                                    else {
                                        throw E2ParserException("无法取源码：${tk!!.v}" ,0)
                                    }
                                }
                            }

                        }


                        // 数组操作
                        "i" -> {
                            val cs = pI(pC, tk.v)
                            pC.clear()
                            if (cs != null) {
                                pC.addAll(cs)
                            }
                        }

                        // 数组到文本
                        "st","it" -> {
                            var xt = ""
                            for (s in pC) {
                                xt += s + tk.v
                            }
                            pC.clear()
                            pC.add(xt)
                        }

                        // 解内容
                        else -> {
                            val xs = p2(tk)
                            pC.clear()
                            if (xs != null) pC.addAll(xs)
                            if (pC.size == 0) pC.add("")
                        }

                    }

                }catch (e : Exception){
                    e.printStackTrace()
                    // 若含or则继续执行，否则输出错误
                    if (tokens.hasOr()){
                        pC.clear()
                        pC.add("")
                    }else{
                        throw E2ParserException(e.toString())
                    }
                }

                tk = tokens.next()
            }

            if (oL == 1){
                oC.addAll(pC)
            }
            else{
                if (oC.size == 0) return pC
                else{
                   if (pC.size > 0){
                       oC[oC.size - 1] += pC[0]
                   }
                }
            }

            return oC
        }

        private fun p2(token: OItem) : List<String>? {
            var ct = ""
            if (pC.size >= 1) {
                ct = pC[0]
                when (token.a) {
                    // 规范代码
                    "get", "css" -> return pCss(ct, token.v)
                    "xml" -> return JsoupParserUtils.xml(ct,token.v)
                    "json" ->  return pJson(ct, token.v)

                    // html 进阶
                    "a", "src", "href" -> return pAttr(ct, token)
                    "byt","bytt" -> return pBytt(ct, token.v)

                    // 正则表达式
                    "z", "zz" -> return pZz(ct, token.v, false)
                    "z2", "zz2" -> return pZz(ct, token.v, true)

                    // 倒序
                    "dx" -> {
                        val v = ArrayList<String>()
                        pC.forEach {
                            v.add(0,it)
                        }
                        return v
                    }

                    // 分割
                    "fg" -> {
                        if (token.v == ""){
                            return ct.split("\n")
                        }else{
                            return ct.split(Regex(token.v))
                        }
                    }

                    // 文本操作 编码
                    "t", "tz", "ty", "th", "tj","ct", "tz2", "ty2","html","tsk","tzc","tzc2",
                    "d","e", "dn", "en", "en64", "dn64", "md5", "invar","tv", "vj","n","th2","time"
                    -> {
                        val v = pText(ct, token).trim()
                        if (v.isEmpty()) return null
                        else {
                            val vs = ArrayList<String>()
                            vs.add(v)
                            return vs
                        }
                    }
                    else -> {
                        throw Exception("未知的函数" + token.a)
                    }
                }
            }
            return null
        }

        // 文本操作
        private fun pText(con: String, token: OItem) : String{
            when(token.a){

                "tsk" -> return con.trim()

                // 最长文本
                "tzc" -> {
                    val size = Jian.toInt(token.v)
                    if (size == 0) return con
                    else if (con.length <= size) return con
                    else return con.substring(0,size)
                }
                "tzc2" -> {
                    val size = Jian.toInt(token.v)
                    if (size == 0) return con
                    else if (con.length <= size) return con
                    else return con.substring(con.length - size)
                }

                "n" -> return ""

                "html" -> return con;

                "t" -> return Jian.def().取网页文本(con)

                "tz" -> return Jian.def().取文本左边(con, token.v) ?: ""

                "tz2" -> return Jian.def().取文本左边2(con, token.v) ?: ""

                "ty" -> return Jian.def().取文本右边(con, token.v) ?: ""

                "ty2" -> return Jian.def().取文本右边2(con, token.v) ?: ""

                "th","th2" -> {
                    val fg = Jian.def().寻找文本2(token.v, "##", 0)

                    // 若没有则将内容替换为空
                    if (fg == -1) return con.replace(token.v,"")
                    val left = token.v.substring(0, fg)
                    val right = token.v.substring(fg + 2)
                    if (token.a == "th"){
                        return con.replace(Regex(left), right)
                    }else{
                        return con.replace(left, right)
                    }
                }

                // 时间戳转换
                "time" -> {
                    // 无参数 返回13位时间戳
                    if (token.v.isEmpty()){
                        return System.currentTimeMillis().toString()
                    }
                    // 一个参数 若为数字10 13 则返回对应长度时间戳 否则返回解析后时间戳
                    else{
                        if (token.v.length == 2){
                            if (token.v == "13") return System.currentTimeMillis().toString()
                            else if (token.v == "10") return (System.currentTimeMillis() / 1000).toString()
                        }

                        // 若前面内容为时间戳则将前面内容转换  若不是则转换当前时间
                        if (con.length == 10 || con.length == 13){
                            // 上面的没执行则执行前面的替换
                            var t = con.toLong()
                            if (con.length == 10) t *= 1000
                            return Jian.def().时间戳到文本(t,token.v)

                        }else{
                            return Jian.def().时间戳到文本(System.currentTimeMillis(),token.v)
                        }
                    }
                }


                "tj","ct" -> return con + token.v

                "dn" -> {
                    var type = token.v
                    if (type.contains(",")){
                        type = Jian.def().取文本左边(type,",") ?: type
                        val value = token.v.split(",")
                        return when(type){
                            "aes" -> {
                                if (value.size == 6){
                                    val pad = value[1] // 加密模式 CBC  ECB CBC CTR OFB CFB
                                    val paww = value[2] // 密码
                                    var code = value[3] // 编码
                                    val mode = value[4] // 输出模式 hex base64
                                    val iv = value[5] // 偏移量

                                    // AES解密(源码，密码，加密模式，偏移量)
                                    if (mode.equals("hex",true)) lei.pJianSystemFun("AES解密",con,mode,paww,pad,iv).toString()
                                    else {
                                        if (code.isEmpty()) code = "utf-8"
                                        lei.pJianSystemFun("AES解密_BASE64",con.toByteArray(Charset.forName(code)),mode,paww,pad,iv).toString()
                                    }
                                    //if (mode == "hex") EncryptUtils.decryptHexStringAES(con,paww.toByteArray(),pad,iv.toByteArray()).toString()
                                    //else EncryptUtils.decryptBase64AES(con.toByteArray(Charset.forName(code)),paww.toByteArray(),pad,iv.toByteArray()).toString()
                                }
                                else ""
                            }

                            "des" -> {
                                if (value.size == 6){
                                    val pad = value[1] // 加密模式 CBC  ECB CBC CTR OFB CFB
                                    val paww = value[2] // 密码
                                    var code = value[3] // 编码
                                    val mode = value[4] // 输出模式 hex base64
                                    val iv = value[5] // 偏移量


                                    if (mode.equals("hex",true)) {
                                        lei.pJianSystemFun("DES解密",con,mode,paww,pad,iv).toString()
                                    }
                                    else {
                                        if (code.isEmpty()) code = "utf-8"
                                        lei.pJianSystemFun("DES解密_BASE64",con.toByteArray(Charset.forName(code)),mode,paww,pad,iv).toString()
                                    }

                                    //if (mode == "hex") EncryptUtils.decryptHexStringDES(con,paww.toByteArray(),pad,iv.toByteArray()).toString()
                                    //else EncryptUtils.decryptBase64DES(con.toByteArray(Charset.forName(code)),paww.toByteArray(),pad,iv.toByteArray()).toString()
                                }
                                else ""
                            }

                            "3des" -> {
                                if (value.size == 6){
                                    val pad = value[1] // 加密模式 CBC  ECB CBC CTR OFB CFB
                                    val paww = value[2] // 密码
                                    var code = value[3] // 编码
                                    val mode = value[4] // 输出模式 hex base64
                                    val iv = value[5] // 偏移量

                                    if (mode.equals("hex",true)) {
                                        lei.pJianSystemFun("3DES解密",con,mode,paww,pad,iv).toString()
                                    }
                                    else {
                                        if (code.isEmpty()) code = "utf-8"
                                        lei.pJianSystemFun("3DES解密_BASE64",con.toByteArray(Charset.forName(code)),mode,paww,pad,iv).toString()
                                    }

                                    //if (code.isEmpty()) code = "utf-8"
                                    //if (mode == "hex") EncryptUtils.decryptHexString3DES(con,paww.toByteArray(),pad,iv.toByteArray()).toString()
                                    //else EncryptUtils.decryptBase64_3DES(con.toByteArray(Charset.forName(code)),paww.toByteArray(),pad,iv.toByteArray()).toString()
                                }
                                else ""
                            }

                            else -> ""
                        }
                    }
                    else{

                        when(token.v){
                            "64","base64" -> return Jian.Value(lei.pJianSystemFun("BASE64解密",con)
                                ?:throw ParserException("读取失败 ${token.v}(${con})",0))
                            // "64","base64" -> return String(Base64.decode(con.toByteArray(), 0))
                            "md5" -> return Jian.def().md5(con)
                        }
                    }

                    return Jian.def().URL解码(con, token.v)


                }
                "en" -> {
                    var type = token.v
                    if (type.contains(",")){
                        type =  Jian.def().取文本左边(type,",")  ?: type
                        val value = token.v.split(",")
                        when(type){
                            "aes" -> {
                                if (value.size == 6){
                                    val pad = value[1] // 加密模式 CBC  ECB CBC CTR OFB CFB
                                    val paww = value[2] // 密码
                                    var code = value[3] // 编码
                                    val mode = value[4] // 输出模式 hex base64
                                    val iv = value[5] // 偏移量
                                    if (code.isEmpty()) code = "utf-8"

                                    // AES加密(源码，编码，密码，加密模式，偏移量)
                                    if (mode.equals("hex",true)) lei.pJianSystemFun("AES加密",code,con,mode,paww,pad,iv).toString()
                                    else {
                                        if (code.isEmpty()) code = "utf-8"
                                        lei.pJianSystemFun("AES加密_BASE64",con.toByteArray(Charset.forName(code)),mode,paww,pad,iv).toString()
                                    }

                                    //if (mode == "hex") EncryptUtils.encryptAES2HexString(con.toByteArray(Charset.forName(code)),paww.toByteArray(),pad,iv.toByteArray()).toString()
                                    //else EncryptUtils.encryptAES2Base64(con.toByteArray(Charset.forName(code)),paww.toByteArray(),pad,iv.toByteArray()).toString()
                                }
                            }

                            "des" -> {
                                if (value.size == 6){
                                    val pad = value[1] // 加密模式 CBC  ECB CBC CTR OFB CFB
                                    val paww = value[2] // 密码
                                    var code = value[3] // 编码
                                    val mode = value[4] // 输出模式 hex base64
                                    val iv = value[5] // 偏移量
                                    if (code.isEmpty()) code = "utf-8"
                                    // DES加密(源码，编码，密码，加密模式，偏移量)
                                    if (mode.equals("hex",true)) lei.pJianSystemFun("DES加密",code,con,mode,paww,pad,iv).toString()
                                    else {
                                        if (code.isEmpty()) code = "utf-8"
                                        lei.pJianSystemFun("DES加密_BASE64",con.toByteArray(Charset.forName(code)),mode,paww,pad,iv).toString()
                                    }

                                   // if (mode == "hex") EncryptUtils.encryptDES2HexString(con.toByteArray(Charset.forName(code)),paww.toByteArray(),pad,iv.toByteArray()).toString()
                                   // else EncryptUtils.encryptDES2Base64(con.toByteArray(Charset.forName(code)),paww.toByteArray(),pad,iv.toByteArray()).toString()
                                }
                            }

                            "3des" -> {
                                if (value.size == 6){
                                    val pad = value[1] // 加密模式 CBC  ECB CBC CTR OFB CFB
                                    val paww = value[2] // 密码
                                    var code = value[3] // 编码
                                    val mode = value[4] // 输出模式 hex base64
                                    val iv = value[5] // 偏移量
                                    if (code.isEmpty()) code = "utf-8"

                                    // DES加密(源码，编码，密码，加密模式，偏移量)
                                    if (mode.equals("hex",true)) lei.pJianSystemFun("3DES加密",code,con,mode,paww,pad,iv).toString()
                                    else {
                                        if (code.isEmpty()) code = "utf-8"
                                        lei.pJianSystemFun("3DES加密_BASE64",con.toByteArray(Charset.forName(code)),mode,paww,pad,iv).toString()
                                    }
                                }
                            }
                        }
                    }

                    else{
                        when(token.v){
                            "64","base64" -> Jian.Value(lei.pJianSystemFun("BASE64解密",con)?:throw ParserException("读取失败 ${token.v}(${con})",0))
                            // "64","base64" -> return String(Base64.decode(con.toByteArray(), 0))
                            "md5" -> return Jian.def().md5(con)
                        }
                    }
                    return Jian.def().URL解码(con, token.v)

                }

                // kotlin 的 垃圾 不会用
                /*"en64" -> return Base64.encode(con.toByteArray())
                "dn64" ->  return String(Base64.getDecoder().decode(encodedString))*/

                "en64" -> return Jian.Value(lei.pJianSystemFun("BASE64加密",con)?:throw ParserException("读取失败 ${token.v}(${con})",0))
                "dn64" -> return Jian.Value(lei.pJianSystemFun("BASE64解密",con)?:throw ParserException("读取失败 ${token.v}(${con})",0))
                "md5" -> return Jian.def().取MD5值(con)

                "vj", "invar" -> return "con" + lei.getVar(token.v)

                else -> return ""
            }

        }

        class E2TokenPraser(val e2Reg: String) {

            // 阅读到的位置
            var readPosition = 0

            // 排除已阅读代码 剩余未阅读的代码
            var waitCode = e2Reg.trim()

            /**
             * 取下一个函数 返回空即没有
             */
            fun next(): OItem? {

                // 内容超出
                if (waitCode.isEmpty()) return null


                val token = OItem()

                // 标准第一个起始符必须为 .
                if (waitCode.substring(0, 1) != ".") {
                    throw Exception("未发现函数起始符 [ . ] ： $waitCode\n")
                }

                // 获取 （ 取函数名称
                val k9 = waitCode.indexOf("(", 0)
                if (k9 == -1) throw Exception("代码无法识别 [ $waitCode ] ")

                // 得到函数名
                token.a = waitCode.substring(1, k9)

                // 移动阅读位置到 （ 之后
                readPosition += k9 + 1

                waitCode = waitCode.substring(k9 + 1)

                // 取参数 判断是否使用了 @@ 其始
                var t0 = false

                if (waitCode.length > 5
                    && waitCode.substring(0, 2) == "@@"
                ) {
                    val k0 = Jian.def().寻找文本2(waitCode, "@@)", 2);
                    if (k0 != -1) {
                        // 参数不包含 @@
                        token.v = waitCode.substring(2, k0)

                        // 阅读位置移动到 )之后
                        readPosition = k0 + 3 //  @@) == 3个字符
                        waitCode = waitCode.substring(k0 + 3)

                        // 已取参数
                        t0 = true
                    }
                }

                // 未取到参数，则标准方式取值
                if (!t0) {
                    val k0 = Jian.def().寻找文本2(waitCode, ")", 0);
                    if (k0 != -1) {
                        token.v = waitCode.substring(0, k0)

                        // 阅读位置移动到 )之后
                        readPosition = k0 + 1 // 即 @@)
                        waitCode = waitCode.substring(k0 + 1)
                    } else {
                        throw Exception("找不到结束符 [ ) ] $waitCode")
                    }
                }
                return token
            }

            /**
             * 未解析到的内容是否含有 .or()
             */
            fun  hasOr() : Boolean{
                return waitCode.contains(".or()")
            }

        }
    }

    /**
     * E2的参数分割有 # 及 小写逗号 如果没有分割参数则返回单个值
     */
    private fun getParameter(parameter : String) : List<String>{
        val ls = ArrayList<String>()
        var pos = 0
        while (pos != -1 && pos < parameter.length){
            val p = Jian.def().寻找文本2(parameter,",",0)
            if (p != -1){
                ls.add(parameter.substring(pos,p))
                pos = p + 1
            }
        }
        if (ls.size == 0){
            while (pos != -1 && pos < parameter.length){
                val p = Jian.def().寻找文本2(parameter,"#",0)
                if (p != -1){
                    ls.add(parameter.substring(pos,p))
                    pos = p
                }
            }
        }

        if (ls.size == 0) ls.add(parameter)

        return ls
    }
    private fun pCss(code: String, parameter: String?): List<String>? {
        try {
            val _keys: MutableList<String> = java.util.ArrayList()
            if (parameter.isNullOrEmpty()) {
                _keys.add(code)
                return _keys
            }
            val _e: Element = Jsoup.parse(code)
            val _es = _e.select(parameter)
            for (e in _es) {
                _keys.add(e.toString())
            }
            return _keys
        } catch (ex: Exception) {
            ex.printStackTrace()
        }
        return null
    }
    private fun pXml(code: String, parameter: String?): List<String>? {
        val _keys: MutableList<String> = java.util.ArrayList()
        if (parameter.isNullOrEmpty()) {
            _keys.add(code)
            return _keys
        }
        // DiaUtils.text(code)
        val _e: Element = Jsoup.parse(code, "", Parser(XmlTreeBuilder()))
        val _es = _e.select(parameter)
        for (e in _es) {
            _keys.add(e.outerHtml())
        }
        return _keys
    }
    private fun pJson(ct: String, parameter: String): List<String>? {
        var code = ct.trim()
        val results: MutableList<String> = ArrayList()

        // 判断是否为html类型.. 访问方式为 jsoup 的自动带html
        if (code.length > 10 && code.substring(0, 1) == "<") code = Jian.def().取网页文本(code) ?: ct
        var jsons: JSONArray? = null // 尝试读取数据数组

        // 参数为空，返回数组对象
        if (parameter.isEmpty()) {
            jsons = try {
                JSONArray(code)
            } catch (ex: Exception) {
                ex.printStackTrace()
                return null
            }
        }

        else {
            // 数组
            if (code.startsWith("[")){
                try {
                    val arrs = JSONArray(code)
                    // 数组的话只能取数字参数
                    Jian.toInt(parameter).let {
                        if (arrs.length() <= it){
                            return null
                        }else{
                            jsons = JSONArray()
                            jsons!!.put(arrs.get(it))
                        }
                    }


                }catch (e : java.lang.Exception){
                    e.printStackTrace()
                    return null
                }

            }else{
                val json = try {
                    JSONObject(code);
                }catch (e : Exception){
                    // e.printStackTrace()
                    //App.log("e",parameter)
                    //throw E3Exception("无法将其转换为JSON对象：$code\n" + e.toString())
                    return null
                }

                // 没有参数
                if (json.isNull(parameter)) return null

                try {
                    jsons = json.getJSONArray(parameter)
                } catch (e: Exception) {

                }

                if (jsons == null) { // 如果不为数组 则先取文本后存至数组中
                    try {
                        jsons = JSONArray()
                        jsons!!.put(json.getString(parameter))
                    } catch (ex: Exception) {
                        return null
                    }
                }
            }


        }

        if (jsons == null) return null

        // 存储数据
        try {
            for (i in 0 until jsons!!.length()) {
                results.add(jsons!![i].toString())
            }
        } catch (ex: Exception) {
            ex.printStackTrace()
        }
        return results
    }

    /**
     * .zz 正则解析
     * @param son 是否取子表达式，否则取数组（如果没有子表达式，则返回数组！）
     * @return
     */
    private fun pZz(code: String?, parameter: String?, son: Boolean): List<String>? {
        if (parameter == null) return null
        val reg: String = kh(parameter) // 将正则中与E2code冲突的符号解释化
        var _results: MutableList<String> = ArrayList()

        val res: List<List<String>> = Jian.def().正则读取(code!!, reg)

        if (res.size == 0) return null
        if (son) {
            // 仅取子表达式
            _results.addAll(res[0])
            if (_results.size > 0) _results.removeAt(0) // 删除第一个
        } else {
            for (re in res) {
                if (re.size < 1) continue  // 空对象
                _results.add(re[0])
            }
        }
        return _results
    }

    /**
     * 数组操作
     */
    private fun pI(_hosts: List<String>, _parameter: String): MutableList<String> {
        /* 多种格式
        * 单值 选择某个
        * 两个值 前、后， 若前或后其中一项留空，则该项至最后或首个
        */
        var parameter = _parameter
        val _results: MutableList<String> = ArrayList()
        parameter = parameter.replace("##", ",") // 统一小写
        parameter = parameter.replace("，", ",") // 统一小写
        if (parameter.contains(",")) { // 读取多个
            val i_left = Jian.def().取文本左边(parameter, ",")
            val i_right = Jian.def().取文本右边(parameter, ",")
            var i_start = 0
            if (!i_left!!.isEmpty()) i_start = i_left.toInt()
            var i_end = 0
            if (!i_right!!.isEmpty()) i_end = i_right.toInt()
            if (i_end < 1) {
                i_end = _hosts.size + i_end // 负数  则减去相对的
            }
            val xels = Elements()
            for (i in _hosts.indices) {
                if (i < i_start || i >= i_end) continue
                _results.add(_hosts[i])
            }
        }
        else {
            var pint = Jian.toInt(parameter)
            if (pint == -1) pint = _hosts.size - 1
            if (_hosts.size < pint) pint = 0

            if (pint < _hosts.size && pint >= 0) {
                _results.add(_hosts[pint])
            }

            else {
                throw Exception("[ .i($parameter) ] 欲取位置[" + pint + "]大于实际内容长度[" + _hosts.size + "] ")
            }
        }
        return _results
    }

    // html 解析 attr
    private fun pAttr(con: String, token: OItem) : List<String>?{
        val e = Jsoup.parse(con).body()
        if (e.childNodeSize() == 0) return null

        val parameter: String = if (token.a == "a") token.v.ifEmpty { "href" } else token.a
        val value = e.child(0).attr(parameter)

        if (value.isNotEmpty()){
            val rst = ArrayList<String>()
            rst.add(value)
            return rst
        }
        return null
    }

    // .byt  html解析取读指定text取对象
    private fun pBytt(code: String?, token: String?): List<String> {
        val _keys: MutableList<String> = java.util.ArrayList()
        val _e = Jsoup.parse(code).body()
        val _es = _e.getElementsMatchingOwnText(token)
        for (e in _es) {
            _keys.add(e.toString())
        }
        return _keys
    }



    // 正则 处理括号的
    private fun kh(reg: String): String {
        var reg = reg
        val zk = "uu89xsdlow" //  (
        val yk = "oo00pxsfwe" //  )
        val xg = "qosdfweix8" //  \
        reg = reg.replace("\\\\".toRegex(), xg)
        reg = reg.replace("\\(".toRegex(), zk)
        reg = reg.replace("\\)".toRegex(), yk)
        reg = reg.replace(xg + zk.toRegex(), zk)
        reg = reg.replace(xg + yk.toRegex(), yk)
        reg = reg.replace(yk.toRegex(), "\\)")
        reg = reg.replace(zk.toRegex(), "\\(")
        reg = reg.replace(xg.toRegex(), "\\\\")
        return reg
    }


}